#include "StdAfx.h"
#include "DebuggerEventHandler.h"

DebuggerEventHandler::DebuggerEventHandler(void) : m_pReceiver(NULL)
{
}

DebuggerEventHandler::~DebuggerEventHandler(void)
{
	UnAdvise();
}

BOOL DebuggerEventHandler::Advise(EnvDTE80::DTE2 *pDTE, IDebuggerEventHandler *pReceiver)
{
	UnAdvise();

	BOOL bRet = FALSE;
	if ((pDTE) && (pReceiver))
	{
		m_pReceiver = pReceiver;

		EnvDTE::EventsPtr spEvents;
		EnvDTE::_DebuggerEventsPtr sp_DebuggerEvents;
		IConnectionPointContainerPtr spCon;

		if (SUCCEEDED(pDTE->get_Events(&spEvents)) &&
			SUCCEEDED(spEvents->get_DebuggerEvents(&sp_DebuggerEvents)) &&
			(spCon = sp_DebuggerEvents) &&
			SUCCEEDED(spCon->FindConnectionPoint(EnvDTE::DIID__dispDebuggerEvents, &m_spCP)) &&
			SUCCEEDED(m_spCP->Advise(this, &m_dwCookie)))
			bRet = TRUE;
	}

	return bRet;
}

void DebuggerEventHandler::UnAdvise()
{
	if (m_spCP)
	{
		m_spCP->Unadvise(m_dwCookie);
		m_spCP = NULL;
	}
	m_pReceiver = NULL;
}

HRESULT STDMETHODCALLTYPE DebuggerEventHandler::QueryInterface(REFIID riid, void** ppvObject)
{
	if (ppvObject == NULL)
		return E_POINTER;

	if ((riid == IID_IUnknown) ||
		(riid == IID_IDispatch) ||
		(riid == EnvDTE::DIID__dispDebuggerEvents))
	{
		*ppvObject = this;
		//AddRef();
		return S_OK;
	}

	return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE DebuggerEventHandler::AddRef(void)
{
	return 1;
}

ULONG STDMETHODCALLTYPE DebuggerEventHandler::Release(void)
{
	return 1;
}

HRESULT STDMETHODCALLTYPE DebuggerEventHandler::GetTypeInfoCount(UINT *pctinfo)
{
	return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE DebuggerEventHandler::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
	return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE DebuggerEventHandler::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
{
	return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE DebuggerEventHandler::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
	switch(dispIdMember)
	{
	case 1:
		m_pReceiver->EnterRunMode((EnvDTE::dbgEventReason)pDispParams->rgvarg[0].ulVal);
		break;
	case 2:
		m_pReceiver->EnterDesignMode((EnvDTE::dbgEventReason)pDispParams->rgvarg[0].ulVal);
		break;
	case 3:
		m_pReceiver->EnterBreakMode((EnvDTE::dbgEventReason)pDispParams->rgvarg[1].ulVal, 
			(EnvDTE::dbgExecutionAction*)pDispParams->rgvarg[0].pulVal);
		break;
	case 4:
		m_pReceiver->ExceptionThrown(pDispParams->rgvarg[4].bstrVal, 
			pDispParams->rgvarg[3].bstrVal, 
			pDispParams->rgvarg[2].ulVal,
			pDispParams->rgvarg[1].bstrVal,
			(EnvDTE::dbgExecutionAction*)pDispParams->rgvarg[0].pulVal);
		break;
	case 5:
		m_pReceiver->ExceptionNotHandled(pDispParams->rgvarg[4].bstrVal, 
			pDispParams->rgvarg[3].bstrVal, 
			pDispParams->rgvarg[2].ulVal,
			pDispParams->rgvarg[1].bstrVal,
			(EnvDTE::dbgExecutionAction*)pDispParams->rgvarg[0].pulVal);
		break;
	case 6:
		{
			EnvDTE::ProcessPtr spProcess = pDispParams->rgvarg[3].pdispVal;
			EnvDTE::ProgramPtr spProgramm = pDispParams->rgvarg[2].pdispVal;
			EnvDTE::ThreadPtr spThread = pDispParams->rgvarg[1].pdispVal;
			EnvDTE::StackFramePtr spStackFrame =  pDispParams->rgvarg[0].pdispVal;

			m_pReceiver->ContextChanged(spProcess, spProgramm, spThread, spStackFrame);
		}
		break;
	}
	return S_OK;
}
